package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.article.client.ArticleFeign;
import com.heima.common.dtos.PageResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;

import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.model.admin.dtos.ChannelDto;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsPageReqDto;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.model.user.dtos.AuthDto;
import com.heima.wemedia.entity.WmMaterial;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.entity.WmUser;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.heima.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author HM
 * @since 2022-04-27
 */
@Service
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    /**
     * 分页查询
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult<WmNewsResultDTO> findByPage(WmNewsPageReqDto dto) {
        //        获取用户id ,登录才能访问
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null || userId == 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        IPage<WmNews> iPage = new Page<>(dto.getPage(), dto.getSize());
//        设置条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getWmUserId, userId);
        // 只有当传递了参数才能查询
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            queryWrapper.like(WmNews::getTitle, dto.getKeyword());
        }
        if (dto.getChannelId() != null) {
            queryWrapper.eq(WmNews::getChannelId, dto.getChannelId());
        }
        if (dto.getBeginPubDate() != null) {
            queryWrapper.gt(WmNews::getPublishTime, dto.getBeginPubDate());
        }
        if (dto.getEndPubDate() != null) {
            queryWrapper.lt(WmNews::getPublishTime, dto.getEndPubDate());
        }
        // 当状态不等于 -1 时则标识查询所有
        if (dto.getStatus() != null && dto.getStatus() != -1) {
            // 待审核,状态有: 1 ,3
            if (dto.getStatus() == 1) {
                // where status in (1,3)
                queryWrapper.in(WmNews::getStatus, new Integer[]{1, 3});
                // 审核成功有 : 4 , 8, 9
            } else if (dto.getStatus() == 4) {
                queryWrapper.in(WmNews::getStatus, new Integer[]{4, 8, 9});
            } else {
                queryWrapper.eq(WmNews::getStatus, dto.getStatus());
            }
        }
//        分页查询
        IPage<WmNews> wmNewsIPage = page(iPage, queryWrapper);
        if (wmNewsIPage == null || CollectionUtils.isEmpty(wmNewsIPage.getRecords())) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 数据转换
        List<WmNewsResultDTO> newsResultDTOS = BeanHelper.copyWithCollection(wmNewsIPage.getRecords(), WmNewsResultDTO.class);
        // 返回
        return new PageResult<>(dto.getPage(), dto.getSize(), wmNewsIPage.getTotal(), newsResultDTOS);
    }


    @Autowired
    private WmNewsMaterialService materialService;

    @Autowired
    private WmNewsAuditService wmNewsAuditService;

    /**
     * 保存草稿,提交审核,修改
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public void submit(WmNewsDto dto) {
        // 获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null || userId == 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 修改时当前文章是否属于当前用户
        if (dto.getId() != null) {
            // 先查询
            WmNews news1 = getById(dto.getId());
            if (news1.getWmUserId().intValue() != userId.intValue()) {
                // 不是当前登录用户的文章不能修改
                throw new LeadException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
            }
        }
        // 对象拷贝
        WmNews wmNews = BeanHelper.copyProperties(dto, WmNews.class);

        // 如果没用数据则添加
        if (dto.getId() == null) {
            wmNews.setWmUserId(userId);
            wmNews.setEnable(true);
            wmNews.setCreatedTime(new Date());
        }

        if (dto.getDraft()) {
            wmNews.setSubmitedTime(new Date());
        }
        // 处理封面图片
        if (!CollectionUtils.isEmpty(dto.getImages())) {
            // 集合转成字符串 , "," 为分隔符
            String images = String.join(",", dto.getImages());
            wmNews.setImages(images);
        }
        // 保存,修改文章
        boolean b = saveOrUpdate(wmNews);
        if (!b) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }

        // 自媒体文章id
        Integer id = wmNews.getId();
        // 查询到数据则是修改
        if (dto.getId() != null) {
            // 处理文章素材的中间表s
            // 先删除文章素材的对应信息
            materialService.removeNewsId(id);
        }

        // 新增文章和素材的中间表数据
        if (CollectionUtils.isEmpty(dto.getImages())) {
            // 处理文章封面
            List<Integer> materialIds = getMaterialIdsByImages(dto.getImages());
            // 批量保存中间表(封面素材信息)
            materialService.saveNewMaterialBatch(id, materialIds, 1);
        }
        // 处理文章内容
        if (StringUtils.isNotBlank(dto.getContent())) {
            List<Integer> materialIds = getMaterialIdsByContent(dto.getContent());
            // 批量保存中间表(封面素材信息)
            materialService.saveNewMaterialBatch(id, materialIds, 0);
        }
        // 如果是提交审核状态,去调用审核的方法
        if (!dto.getDraft()) {
            // 异步调用,加注解
            wmNewsAuditService.auditWmNews(id);
        }
    }

    /**
     * 从文章内容获取素材的id
     *
     * @param content
     * @return
     */
    private List<Integer> getMaterialIdsByContent(String content) {
        // 前端传递json格式,解析json

        List<Map<String, Object>> list = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, Object>>>() {
        });

        List<Integer> ids = new ArrayList<>();

        for (Map<String, Object> map : list) {
            // 根据键找值
            String type = map.get("type").toString();
            // 如果是文本则跳过,我们需要id
            if (type.equals("text")) {
                continue;
            }
            Integer materialId = Integer.valueOf(map.get("id").toString());

            ids.add(materialId);
        }

        return ids;
    }

    @Autowired
    private WmMaterialService wmMaterialService;

    /**
     * 处理封面获取素材的id
     *
     * @param images
     * @return
     */
    private List<Integer> getMaterialIdsByImages(List<String> images) {
        // 查询条件
        LambdaQueryWrapper<WmMaterial> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(WmMaterial::getUrl, images);
        List<WmMaterial> wmMaterialList = wmMaterialService.list();
        // 映射收集
        List<Integer> ids = wmMaterialList
                .stream()
                .map(WmMaterial::getId)
                .collect(Collectors.toList());

        return ids;
    }


    /**
     * kafka
     */
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    /**
     * 自媒体文章上下架
     *
     * @param dto
     * @return
     */
    public void downOrUp(WmNewsDto dto) {
        // 拿到用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null || userId == 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 修改要求
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getWmUserId, userId).eq(WmNews::getId, dto.getId());
        // 先查询一遍,看看是否有数据
        WmNews wmNews1 = getOne(queryWrapper);
        if (wmNews1 == null) {
            log.error("没用查询到用户");
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 如果有数据,查看状态是否为未发布状态
        if (wmNews1.getStatus() != 9) {
            log.error("文章不是发布状态");
            throw new LeadException(AppHttpCodeEnum.CAN_NOT_DOWNORUP);
        }
        // 创建结果集
        WmNews wmNews = new WmNews();
        wmNews.setId(dto.getId());
        wmNews.setEnable(dto.getEnable());
        // 调用修改
        boolean b = updateById(wmNews);
        if (!b) {
            log.error("修改状态失败==={}");
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }

        // 传入map集合
        Map<String, Long> map = new HashMap<>();
        map.put("articleId", wmNews.getArticleId());
        map.put("enable", wmNews.getEnable() ? 1L : 0L);
        // 发送消息给kafka
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC, JsonUtils.toString(map));
    }


    @Autowired
    private WmUserService wmUserService;


    /**
     * 分页媒体审核查询
     *
     * @param dto
     * @return
     */
    public PageResult<WmNewsResultDTO> findByAllPage(ChannelDto dto) {
        // 构造查询条件
        IPage<WmNews> iPage = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getStatus, 3);
        IPage<WmNews> wmNewsIPage = page(iPage, queryWrapper);

        if (wmNewsIPage == null) {
            log.error("没有查询到自媒体");
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        Integer id = dto.getId();
        List<WmNewsResultDTO> wmNewsResultDTOS = baseMapper.findByPageWmNewResult(id);


        // List<WmNewsResultDTO> wmNewsResultDTOS = BeanHelper.copyWithCollection(wmNewsIPage.getRecords(), WmNewsResultDTO.class);

        // 返回结果
        return new PageResult<>(dto.getPage(), dto.getSize(), wmNewsIPage.getTotal(), wmNewsResultDTOS);
    }


    /**
     * 文章详情
     *
     * @param id
     * @return
     */
    public WmNewsResultDTO findByIdWmNewsDto(Integer id) {

        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getId, id);

        WmNews wmNews = getOne(queryWrapper);
        // 作者id
        Integer wmUserId = wmNews.getWmUserId();
        // 根据id查询
        LambdaQueryWrapper<WmUser> queryWrapper1 = new LambdaQueryWrapper<>();

        queryWrapper1.eq(WmUser::getId, wmUserId);
        WmUser wmUser = wmUserService.getOne(queryWrapper1);
        WmNewsResultDTO resultDTO = new WmNewsResultDTO();

        if (wmUser != null && wmUser.getName() != null && wmUser.getName() != "") {
            resultDTO.setAuthorName(wmUser.getName());
        }
        resultDTO.setId(wmNews.getId());
        resultDTO.setWmUserId(wmUserId);
        resultDTO.setTitle(wmNews.getTitle());
        resultDTO.setContent(wmNews.getContent());
        resultDTO.setType(wmNews.getType());
        resultDTO.setChannelId(wmNews.getChannelId());
        resultDTO.setLabels(wmNews.getLabels());
        resultDTO.setCreatedTime(wmNews.getCreatedTime());
        resultDTO.setSubmitedTime(wmNews.getSubmitedTime());
        resultDTO.setPublishTime(wmNews.getPublishTime());
        resultDTO.setReason(wmNews.getReason());
        resultDTO.setArticleId(wmNews.getArticleId());
        resultDTO.setImages(wmNews.getImages());
        resultDTO.setEnable(wmNews.getEnable());

        return resultDTO;
    }


    @Autowired
    private ArticleFeign feign;

    /**
     * 根据id 查询自媒体文章
     *
     * @param id
     * @return
     */
    public ArticleDto selectOneArticle(Integer id) {

        // 用户登录
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null || userId == 0) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }

        return feign.selectOneArticle(id);
    }

    /**
     * 删除自媒体文章
     *
     * @param id
     * @return
     */
    public void deleteByIdArticle(Integer id) {
        feign.deleteByIdArticle(id);
    }


    /**
     * 审核通过
     *
     * @param dto
     * @return
     */
    public void setArticleByDto(AuthDto dto) {
        WmNews wmNews = new WmNews();
        wmNews.setId(dto.getId());
        // 已发布
        wmNews.setStatus(9);

        updateById(wmNews);


        // 如果已发布则需要保存到发布表中
        // 调用article 服务接口

        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getId, wmNews.getId());
        WmNews wmNews1 = getOne(queryWrapper);

        WmNewsResultDTO wmNewsResultDTO = new WmNewsResultDTO();

        BeanUtils.copyProperties(wmNews1, wmNewsResultDTO);
        wmNewsResultDTO.setWmUserId(wmNews1.getWmUserId());


        // 查询用户信息
        LambdaQueryWrapper<WmUser> queryWrapper1 = new LambdaQueryWrapper<>();

        queryWrapper1.eq(WmUser::getId, wmNews1.getWmUserId());


        WmUser wmUser = wmUserService.getOne(queryWrapper1);
        try {

            if (wmUser == null) {
                log.error("用户数据不存在");
            }
        } catch (Exception e) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        } finally {


            wmNewsResultDTO.setAuthorName(wmUser.getName());
            wmNewsResultDTO.setArticleId(wmUser.getId().longValue());

            // 保存文章到发布表
            feign.saveById(wmNewsResultDTO);
        }
    }
}
